import { Injectable, NestInterceptor, ExecutionContext, CallHandler, BadGatewayException, HttpStatus } from '@nestjs/common';
import { Observable, throwError, of } from 'rxjs';
import { tap, map, catchError } from 'rxjs/operators';

import RSA from '../common/rsa'
import utils from 'src/common/utils';
import { RateLimiterService } from 'src/entity/rateLimiter/rateLimiter.service';
import { RateLimiterMemory } from 'rate-limiter-flexible';
import { HOSTNAME } from 'src/setting';
let rateLimiter = new RateLimiterMemory({
  keyPrefix: 'rateLimiter',
  points: 1000,
  duration: 1
});

@Injectable()
export class ValidRSAInterceptor implements NestInterceptor {
  
  async consume() {
    let key = HOSTNAME
    return new Promise((resolve, reject)=> {
      let loop = async () => {
        try {
          const res = await rateLimiter.consume(key);
          resolve(res)
        } catch (err) {
          setTimeout(() => {
            loop()
          }, 1000)
        }
      }
      loop()
    })
  }

  intercept(context: ExecutionContext, next: CallHandler): any {
    const req = context.switchToHttp().getRequest();
    const res = context.switchToHttp().getResponse();

    const callError = (message) => {
      const status = HttpStatus.UNAUTHORIZED;
      res.status(status);
      const errorResponse = {
        message: message,
        status: status, // 自定义code
        url: req.originalUrl, // 错误的url地址
      };
      return errorResponse
    }

    
    let token = req.headers.token
    if(!token) {
      let message = '非法操作'
      return of(callError(message));
    }else{
      return new Promise(async (resolve, reject) => {
        let result = await this.consume()
        if(result){
          //验证rsa
          try{
            let body = req.query
            if(req.method.toString().toLowerCase() === 'post'){
              body = JSON.parse(JSON.stringify(req.body))
            }
            let newBody = {}
            let loop = (data, key) => {
              if(data[key]){
                if(typeof(data[key]) === 'string'){
                  data[key] = utils.utf16toEntities(data[key])
                }else if(typeof(data[key]) === 'object'){
                  for(let keyTwo in data[key]){
                    loop(data[key], keyTwo)
                  }
                }
              }
            }
            for(let key in body){
              newBody[key] = body[key]
              if(newBody[key] && typeof(newBody[key]) === 'string' && newBody[key].length > 200){
                newBody[key] = newBody[key].substring(0,200)
              }
              if(newBody[key]){
                loop(newBody, key)
              }
            }
            let method = req.route.methods.get ? 'get' : req.route.methods.post ? 'post' : ''
            method = method.toLocaleUpperCase()
            let path = req.route.path
            let context = `${method}\n${path}\n${JSON.stringify(newBody)}\n`
            if(!RSA.Decrypt(token, context)){
              throw new Error('填写内容有误，请检查。')
            }else{
              resolve(next.handle().pipe(
                map(data => {
                  return data
                })
              ))
            }
          }catch(err) {
            resolve(of(callError(err.toString())))
          }
        }else{
          resolve(of(callError('网络拥挤，请重试')))
        }
        
        // resolve(next.handle().pipe(
        //   map(data => {
        //     return data
        //   })
        // ))
      })


      

    }
  }
}
